package com.wang.di.core.manager;

import com.wang.di.core.bean.BaseBean;
import com.wang.di.core.exception.BeanInitException;
import com.wang.di.core.exception.BeanMatchException;

import java.lang.annotation.Annotation;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class BeanManager {
    private Map<Class<?>, List<BaseBean>> beanMap;
    private Map<Class<? extends Annotation>, Class<? extends BaseBean>> beanClzMap;

    public BeanManager(Map<Class<? extends Annotation>, Class<? extends BaseBean>> beanClzMap) {
        this.beanClzMap = beanClzMap;
    }

    public <T> T get(Class<T> clz, Object... cond) throws BeanMatchException, BeanInitException {
        List<BaseBean> beanList = this.beanMap.get(clz);
        BaseBean theBean = null;
        if (beanList == null || beanList.size() == 0) {
            throw new BeanMatchException();
        } else if (beanList.size() == 1) {
            theBean = beanList.get(0);
        } else {
            for (BaseBean bean : beanList) {
                if (!bean.check(cond)) continue;
                theBean = bean;
            }
            if (theBean == null) {
                throw new BeanMatchException();
            }
        }
        return (T) theBean.get();
    }

    // 对类进行扫描整理
    public void injectClass(List<Class<?>> clzList) throws BeanInitException {
        Map<Class<?>, List<BaseBean>> map = new HashMap<>();
        for (Class<?> clz : clzList) {
            Class<? extends BaseBean> beanClz = null;
            Annotation registerAnno = null;
            for (Annotation a : clz.getAnnotations()) {
                boolean isRegister = beanClzMap.containsKey(a.annotationType());
                if (!isRegister) continue;
                beanClz = beanClzMap.get(a.annotationType());
                registerAnno = a;
                break;
            }
            if (beanClz == null) continue;
            BaseBean bean = null;
            try {
                bean = beanClz.getConstructor(Class.class, registerAnno.annotationType()).newInstance(clz, registerAnno);
            } catch (Exception e) {
                throw new BeanInitException();
            }
            // 类型向上遍历
            Class<?> tClz = clz;
            while (!tClz.equals(Object.class)) {
                List<BaseBean> beanList = map.computeIfAbsent(tClz, k -> new ArrayList<>());
                beanList.add(bean);
                tClz = tClz.getSuperclass();
            }
        }
        this.beanMap = map;
    }
}
